#include "board.h"

uint16_t	LCD_X_LENGTH=LCD_PIXEL_LESS;
uint16_t	LCD_Y_LENGTH=LCD_PIXEL_MORE;



/**
  * @brief  LCD相关的GPIO管脚初始化
  * @param  无
  * @retval 无
  */
static void LCD_GPIO_Init(void)
{
	/**先开启GPIO的时钟*/
	rcu_periph_clock_enable(LCD_DB0_GPIO_CLK); //开启GPIO的时钟
	rcu_periph_clock_enable(LCD_DB1_GPIO_CLK);
	rcu_periph_clock_enable(LCD_DB2_GPIO_CLK);
	rcu_periph_clock_enable(LCD_DB3_GPIO_CLK);
	rcu_periph_clock_enable(LCD_DB4_GPIO_CLK);
	rcu_periph_clock_enable(LCD_DB5_GPIO_CLK);
	rcu_periph_clock_enable(LCD_DB6_GPIO_CLK);
	rcu_periph_clock_enable(LCD_DB7_GPIO_CLK);

	rcu_periph_clock_enable(LCD_RST_GPIO_CLK);
	rcu_periph_clock_enable(LCD_RS_GPIO_CLK);
	rcu_periph_clock_enable(LCD_WR_GPIO_CLK);
	rcu_periph_clock_enable(LCD_RD_GPIO_CLK);

    gpio_mode_set(LCD_DB0_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB0_GPIO_PIN);
    gpio_output_options_set(LCD_DB0_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB0_GPIO_PIN);

    gpio_mode_set(LCD_DB1_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB1_GPIO_PIN);
    gpio_output_options_set(LCD_DB1_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB1_GPIO_PIN);

    gpio_mode_set(LCD_DB2_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB2_GPIO_PIN);
    gpio_output_options_set(LCD_DB2_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB2_GPIO_PIN);

    gpio_mode_set(LCD_DB3_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB3_GPIO_PIN);
    gpio_output_options_set(LCD_DB3_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB3_GPIO_PIN);

    gpio_mode_set(LCD_DB4_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB4_GPIO_PIN);
    gpio_output_options_set(LCD_DB4_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB4_GPIO_PIN);

    gpio_mode_set(LCD_DB5_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB5_GPIO_PIN);
    gpio_output_options_set(LCD_DB5_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB5_GPIO_PIN);

    gpio_mode_set(LCD_DB6_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB6_GPIO_PIN);
    gpio_output_options_set(LCD_DB6_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB6_GPIO_PIN);

    gpio_mode_set(LCD_DB7_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_DB7_GPIO_PIN);
    gpio_output_options_set(LCD_DB7_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_DB7_GPIO_PIN);

    gpio_mode_set(LCD_RST_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_RST_GPIO_PIN);
    gpio_output_options_set(LCD_RST_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_RST_GPIO_PIN);

    gpio_mode_set(LCD_RS_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_RS_GPIO_PIN);
    gpio_output_options_set(LCD_RS_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_RS_GPIO_PIN);

    gpio_mode_set(LCD_WR_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_WR_GPIO_PIN);
    gpio_output_options_set(LCD_WR_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_WR_GPIO_PIN);

    gpio_mode_set(LCD_RD_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,LCD_RD_GPIO_PIN);
    gpio_output_options_set(LCD_RD_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,LCD_RD_GPIO_PIN);
}


/**
  * @brief  LCD写8位命令函数
  * @param  无
  * @retval 无
  */
void LCD_WriteCMD8(uint16_t cmd)
{
	LCD_RD_SET;
	LCD_RS_CLR;
	DATA_OUT(cmd);
	LCD_WR_CLR;
	LCD_WR_SET;
}

/**
  * @brief  LCD写16位命令函数
  * @param  无
  * @retval 无
  */
void LCD_WriteCMD16(uint16_t cmd)
{
	LCD_RD_SET;
	LCD_RS_CLR;
	DATA_OUT(cmd >> 8);
	LCD_WR_CLR;
	LCD_WR_SET;
	DATA_OUT(cmd);
	LCD_WR_CLR;
	LCD_WR_SET;
}

/**
  * @brief  LCD写8位数据函数(写命令)
  * @param  无
  * @retval 无
  */
void LCD_WriteData8(uint16_t dat)
{
	LCD_RD_SET;
	LCD_RS_SET;
	DATA_OUT(dat);
	LCD_WR_CLR;
	LCD_WR_SET;
}

/**
  * @brief  LCD写16位数据函数(写命令)
  * @param  无
  * @retval 无
  */
void LCD_WriteData16(uint16_t dat)
{
	LCD_RD_SET;
	LCD_RS_SET;
	DATA_OUT(dat >> 8);
	LCD_WR_CLR;
	LCD_WR_SET;
	DATA_OUT(dat);
	LCD_WR_CLR;
	LCD_WR_SET;
}

/**
  * @brief  LCD写寄存器函数
  * @param  无
  * @retval 无
  */
void LCD_WriteRegister(uint16_t reg, uint16_t dat)
{
	LCD_WriteCMD16(reg);
	LCD_WriteData16(dat);
}

/**
* @brief  简单的延时函数(GD32F330CBT6 84MHz),示波器的干活
  * @param  nCount :控制延时时间的值
  * @retval None
  */
void delay_ms(uint32_t nCount)
{
  uint32_t i = 0;
  while (nCount--)
  { //84MHz 28008 Keil 2(default级),3级优化  1ms       20980 Keil 1 ,0级优化  1ms  
    i = 28008; //自己定义
    while (i--)
    {
      ;
    }
  }
}

/**
  * @brief  GC9306初始化
  * @param  无
  * @retval 无
  */
static void LCD_Init_GC9306(void)
{
	//------------- Reset Sequence---------------//
	LCD_RST_SET;
	delay_ms(240);
	LCD_RST_CLR;
	delay_ms(200); // delay 10ms This delay time is necessary
	LCD_RST_SET;
	delay_ms(240);
	//------------end Reset Sequence-----------//
	LCD_WriteCMD8(0xfe);

	LCD_WriteCMD8(0xef);

	LCD_WriteCMD8(0x36);  //旋转屏幕
	LCD_WriteData8(0xc8); //高四位是控制屏幕方向的

	LCD_WriteCMD8(0x3a);
	LCD_WriteData8(0x05);

	LCD_WriteCMD8(0xad);
	LCD_WriteData8(0x33);

	LCD_WriteCMD8(0xaf);
	LCD_WriteData8(0x55);

	LCD_WriteCMD8(0xae);
	LCD_WriteData8(0x2b);
	//----------------------------------end    display    control setting--------------------------------//
	//----------------------------------Power Control Registers Initial--------------------------------//
	LCD_WriteCMD8(0xa4);
	LCD_WriteData8(0x44);
	LCD_WriteData8(0x44);

	LCD_WriteCMD8(0xa5);
	LCD_WriteData8(0x42);
	LCD_WriteData8(0x42);

	LCD_WriteCMD8(0xaa);
	LCD_WriteData8(0x88);
	LCD_WriteData8(0x88);

	LCD_WriteCMD8(0xae);
	LCD_WriteData8(0x2b);

	LCD_WriteCMD8(0xe8);
	LCD_WriteData8(0x11);
	LCD_WriteData8(0x0b);

	LCD_WriteCMD8(0xe3);
	LCD_WriteData8(0x01);
	LCD_WriteData8(0x10);

	LCD_WriteCMD8(0xff);
	LCD_WriteData8(0x61);

	LCD_WriteCMD8(0xAC);
	LCD_WriteData8(0x00);

	LCD_WriteCMD8(0xAf);
	LCD_WriteData8(0x67);

	LCD_WriteCMD8(0xa6);
	LCD_WriteData8(0x2a);
	LCD_WriteData8(0x2a);

	LCD_WriteCMD8(0xa7);
	LCD_WriteData8(0x2b);
	LCD_WriteData8(0x2b);

	LCD_WriteCMD8(0xa8);
	LCD_WriteData8(0x18);
	LCD_WriteData8(0x18);

	LCD_WriteCMD8(0xa9);
	LCD_WriteData8(0x2a);
	LCD_WriteData8(0x2a);
	//---------------------------------display window 240X320-------------------------------------//
	LCD_WriteCMD8(0x2a);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0xef);

	LCD_WriteCMD8(0x2b);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x01);
	LCD_WriteData8(0x3f);

	LCD_WriteCMD8(0x2c);
	//------------------------------------end display window ------------------------------------------//
	//----------------------------------------gamma setting----------------------------------------------//
	LCD_WriteCMD8(0xf0);
	LCD_WriteData8(0x02);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x1b);
	LCD_WriteData8(0x1f);
	LCD_WriteData8(0xb);

	LCD_WriteCMD8(0xf1);
	LCD_WriteData8(0x01);
	LCD_WriteData8(0x3);
	LCD_WriteData8(0x00);
	LCD_WriteData8(0x28);
	LCD_WriteData8(0x2b);
	LCD_WriteData8(0xe);

	LCD_WriteCMD8(0xf2);
	LCD_WriteData8(0xb);
	LCD_WriteData8(0x08);
	LCD_WriteData8(0x3b);
	LCD_WriteData8(0x04);
	LCD_WriteData8(0x03);
	LCD_WriteData8(0x4c);

	LCD_WriteCMD8(0xf3);
	LCD_WriteData8(0xe);
	LCD_WriteData8(0x7);
	LCD_WriteData8(0x46);
	LCD_WriteData8(0x4);
	LCD_WriteData8(0x5);
	LCD_WriteData8(0x51);

	LCD_WriteCMD8(0xf4);
	LCD_WriteData8(0x08);
	LCD_WriteData8(0x15);
	LCD_WriteData8(0x15);
	LCD_WriteData8(0x1f);
	LCD_WriteData8(0x22);
	LCD_WriteData8(0x0F);

	LCD_WriteCMD8(0xf5);
	LCD_WriteData8(0xb);
	LCD_WriteData8(0x13);
	LCD_WriteData8(0x11);
	LCD_WriteData8(0x1f);
	LCD_WriteData8(0x21);
	LCD_WriteData8(0x0F);
	//------------------------------------end gamma setting------------------------------------------//
	LCD_WriteCMD8(0x11);
	delay_ms(120);
	LCD_WriteCMD8(0x29);
}

/**
  * @brief  设置GC9306的GRAM扫描方式
  * @param  ucOption :可选RAM的扫描方向
  * 	@arg 0-7:参数可选值为0-7这8个方向
  * @retval 无
 * @note  坐标图例：A表示向上,V表示向下,<表示向左,>表示向右
 * 				   X表示X轴,Y表示Y轴
 * --------------------------------------------------------------------------------------------------
 * 模式0：      | 模式1：       | 模式2：      |  模式3:
 * 		  A    |   		  A    |  A          |  A
 * 		  |    |          |    |  |          |  |
 * 		  Y0   |          X1   |  Y2         |  X3
 * <----X0.	   |   <----Y1.    |  . X2---->  |  . Y3---->
 * --------------------------------------------------------------------------------------------------
 * 模式4：      | 模式5：       | 模式6：      |  模式7:
 * <----X4.	   | <----Y5.	   |  . X6---->  |  . Y7---->
 * 		  Y4   | 		 X5    |  Y6         |  X7
 * 		  |    | 		 |     |  |          |  |
 *        V    |         V     |  V          |  V
 * --------------------------------------------------------------------------------------------------
 *
 * 								LCD屏示例
 *                         --------------------
 * 						   |                  |
 * 						   |    野火Logo      |
 *  					   |                  |
 *  					   |                  |
 *  					   |                  |
 *  					   |                  |
 *  					   |                  |
 *                         --------------------
 *                         屏幕正面(宽240,高320)
 * ****************************************************************************************************
*/
void LCD_GC9306_GramScan(uint8_t ucOption)
{
	//参数检查,只可输入0-7
	if (ucOption > 7) //神奇的操作
	{
		return;
	}
	//根据模式更新LCD_SCAN_MODE的值,主要用于触摸屏选择计算参数
	//LCD_SCAN_MODE=ucOption;    //LCD_SCAN_MODE是一个全局变量，这里会对其进行赋值
	//根据模式更新XY方向的像素宽度
	if ((ucOption % 2) == 0) //1,3,5,7这几个被排除
	{
		// 0 2 4 6模式下X方向像素宽度为240,Y方向为320，显示的图像是竖着的
		LCD_X_LENGTH = LCD_PIXEL_LESS;
		LCD_Y_LENGTH = LCD_PIXEL_MORE;
	}
	else
	{
		// 1 3 5 7模式下X方向像素宽度为320,Y方向为240，显示的图像是横着的
		LCD_X_LENGTH = LCD_PIXEL_MORE;
		LCD_Y_LENGTH = LCD_PIXEL_LESS;
	}
	//0x36命令参数的高3位可用于设置GRAM的扫描方向
	LCD_WriteCMD8(0x36);					//内存访问控制
	LCD_WriteData8(0x08 | (ucOption << 5)); //根据ucOption的值设置LCD参数,共0-7种模式

	LCD_WriteCMD8(CMD_SetCoordinateX);				  //设置X轴的范围
	LCD_WriteData8(0x00);							  //x起始坐标高8位  坐标是从0开始的
	LCD_WriteData8(0x00);							  //x起始坐标低8位
	LCD_WriteData8(((LCD_X_LENGTH - 1) >> 8) & 0xFF); //无符号数左移(x结束坐标高8位)
	LCD_WriteData8((LCD_X_LENGTH - 1) & 0xFF);		  //x结束坐标低8位

	LCD_WriteCMD8(CMD_SetCoordinateY);				  //设置Y轴的范围
	LCD_WriteData8(0x00);							  //y起始坐标高8位  坐标是从0开始的
	LCD_WriteData8(0x00);							  //y起始坐标低8位
	LCD_WriteData8(((LCD_Y_LENGTH - 1) >> 8) & 0xFF); //无符号数左移(y结束坐标高8位)
	LCD_WriteData8((LCD_Y_LENGTH - 1) & 0xFF);

	LCD_WriteCMD8(CMD_SetPixel); //将像素地址指针归零(复位)
}

/**
 * @brief LCD初始化函数(这里也包括背光控制)
 * @param  无
 * @retval 无
 */
void LCD_Init(void)
{
	LCD_GPIO_Init();
	LCD_Init_GC9306();
	LCD_GC9306_GramScan(0);    //这里的模式是慢慢试出来的
	TIM15_Configuration();
	if(ConfigParam.WorkingMode.working_mode==ENUM_FUMIGATE_NORMAL_MODE || ConfigParam.WorkingMode.working_mode==ENUM_FUMIGATE_ENCHANCE_MODE)
	{	//熏蒸状态,直接搞到100
		SetBackLightIntensity(100);
	}
	else
	{
		if(ConfigParam.RepelSetting.repel_backlight_sett.backlight_auto==false)
		{	//手动背光时,是多少就是多少
			SetBackLightIntensity(ConfigParam.RepelSetting.repel_backlight_sett.backlight);
		}
		else
		{	//自动背光,默认是100
			SetBackLightIntensity(100);
		}
	}
}


/**
 * @brief 在LCD显示器上开辟一个窗口(显示用)
 * @param usX :在特定扫描方向下窗口的起点X坐标 范围:1-240
 * @param usY :在特定扫描方向下窗口的起点Y坐标 范围:1-320
 * @param usWidth :窗口的宽度                  范围:240-1
 * @param usHeight:窗口的高度                  范围:320-1
 * @retval 无
 */
 void LCD_OpenWindow(uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight)
{
	if (usX == 0 || usY == 0 || usWidth == 0 || usHeight == 0)
	{ //传过来的参数不能为0
		return;
	}
	usX -= 1; //外面参数的取址范围为 1-320(或240)
	usY -= 1; //但实际上里面只接受0-299(或239)
	usWidth -= 1;
	usHeight -= 1; //这些自减也就是为了实现这个目的
	//其实也就是重新设置x轴和y轴的范围
	LCD_WriteCMD16(CMD_SetCoordinateX);
	LCD_WriteData16(usX);	 //这个是设置x轴的起始位置
	LCD_WriteData16(usX + usWidth); //高8位  //这个是设置x轴的终止位置

	LCD_WriteCMD16(CMD_SetCoordinateY);
	LCD_WriteData16(usY);	//这个是设置y轴的起始位置
	LCD_WriteData16(usY + usHeight);//这个是设置y轴的终止位置
	//LCD_WriteCMD8(CMD_SetPixel); //将像素地址指针归零(复位,仅限此窗口中)
}

/**
 *	@brief 在LCD显示器上以某一颜色填充像素点   在此之前得先开一个窗口,确定x和y的变化范围
 *	@param ulAmout_Point :要填充颜色像素点的总数目
 *  @param usColor :颜色
 *  @retval 无
 */
 void LCD_FillColor(uint32_t ulAmout_Point,uint16_t usColor)
{
    uint32_t i=0;
    /*memory write*/
    LCD_WriteCMD8(CMD_SetPixel); //将像素地址指针复位(只是回到自定义边框的初始位置)
    for(i=0; i<ulAmout_Point; ++i)
    {	
		//delay_ms(100);
        LCD_WriteData16(usColor);  //看来是逐个点亮
    }
}
